{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using backend: pytorch\n"
     ]
    }
   ],
   "source": [
    "import dgl.nn as dglnn\n",
    "from dgl import from_networkx\n",
    "import torch.nn as nn\n",
    "import torch as th\n",
    "import torch.nn.functional as F\n",
    "import dgl.function as fn\n",
    "import networkx as nx\n",
    "import pandas as pd\n",
    "import socket\n",
    "import struct\n",
    "import random\n",
    "from sklearn.preprocessing import LabelEncoder\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.model_selection import train_test_split\n",
    "import category_encoders as ce\n",
    "from sklearn.decomposition import PCA\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = pd.read_csv('ton_iot.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "scanning      7140161\n",
       "ddos          6165008\n",
       "dos           3375328\n",
       "xss           2108944\n",
       "password      1365958\n",
       "normal         788599\n",
       "backdoor       508116\n",
       "injection      452659\n",
       "ransomware      72805\n",
       "mitm             1052\n",
       "Name: type, dtype: int64"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.type.value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = data.drop(data[(data.type == 'mitm') & (data.type > 'ransomware')].index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "mitm = data[data['type'] == 'mitm']\n",
    "ransomware = data[data['type'] == 'ransomware']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = df.sample(frac=0.1,random_state = 42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = pd.concat([df,mitm,ransomware], axis=0, ignore_index=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ts</th>\n",
       "      <th>src_ip</th>\n",
       "      <th>src_port</th>\n",
       "      <th>dst_ip</th>\n",
       "      <th>dst_port</th>\n",
       "      <th>proto</th>\n",
       "      <th>service</th>\n",
       "      <th>duration</th>\n",
       "      <th>src_bytes</th>\n",
       "      <th>dst_bytes</th>\n",
       "      <th>...</th>\n",
       "      <th>http_response_body_len</th>\n",
       "      <th>http_status_code</th>\n",
       "      <th>http_user_agent</th>\n",
       "      <th>http_orig_mime_types</th>\n",
       "      <th>http_resp_mime_types</th>\n",
       "      <th>weird_name</th>\n",
       "      <th>weird_addl</th>\n",
       "      <th>weird_notice</th>\n",
       "      <th>label</th>\n",
       "      <th>type</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1556025919</td>\n",
       "      <td>192.168.1.32</td>\n",
       "      <td>55827.0</td>\n",
       "      <td>192.168.1.186</td>\n",
       "      <td>8586.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>scanning</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1556294902</td>\n",
       "      <td>192.168.1.30</td>\n",
       "      <td>51524.0</td>\n",
       "      <td>192.168.1.195</td>\n",
       "      <td>80.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>http</td>\n",
       "      <td>0.022213</td>\n",
       "      <td>155.0</td>\n",
       "      <td>978.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>password</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1556025887</td>\n",
       "      <td>192.168.1.32</td>\n",
       "      <td>55428.0</td>\n",
       "      <td>192.168.1.195</td>\n",
       "      <td>1314.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>scanning</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1556079325</td>\n",
       "      <td>192.168.1.31</td>\n",
       "      <td>58876.0</td>\n",
       "      <td>192.168.1.195</td>\n",
       "      <td>513.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>scanning</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1556021906</td>\n",
       "      <td>192.168.1.32</td>\n",
       "      <td>53925.0</td>\n",
       "      <td>192.168.1.133</td>\n",
       "      <td>5950.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>scanning</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2271715</th>\n",
       "      <td>1556429194</td>\n",
       "      <td>192.168.1.37</td>\n",
       "      <td>38131.0</td>\n",
       "      <td>192.168.1.193</td>\n",
       "      <td>445.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000029</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>ransomware</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2271716</th>\n",
       "      <td>1556429475</td>\n",
       "      <td>192.168.1.37</td>\n",
       "      <td>44413.0</td>\n",
       "      <td>13.55.50.68</td>\n",
       "      <td>123.0</td>\n",
       "      <td>udp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.012730</td>\n",
       "      <td>48.0</td>\n",
       "      <td>48.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>ransomware</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2271717</th>\n",
       "      <td>1556429477</td>\n",
       "      <td>192.168.1.33</td>\n",
       "      <td>39296.0</td>\n",
       "      <td>203.14.129.10</td>\n",
       "      <td>123.0</td>\n",
       "      <td>udp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.032825</td>\n",
       "      <td>48.0</td>\n",
       "      <td>48.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>ransomware</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2271718</th>\n",
       "      <td>1556431523</td>\n",
       "      <td>192.168.1.37</td>\n",
       "      <td>37268.0</td>\n",
       "      <td>13.55.50.68</td>\n",
       "      <td>123.0</td>\n",
       "      <td>udp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.012950</td>\n",
       "      <td>48.0</td>\n",
       "      <td>48.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>ransomware</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2271719</th>\n",
       "      <td>1556431525</td>\n",
       "      <td>192.168.1.33</td>\n",
       "      <td>37866.0</td>\n",
       "      <td>203.14.129.10</td>\n",
       "      <td>123.0</td>\n",
       "      <td>udp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.034296</td>\n",
       "      <td>48.0</td>\n",
       "      <td>48.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1.0</td>\n",
       "      <td>ransomware</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2271720 rows × 45 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                 ts        src_ip  src_port         dst_ip  dst_port proto  \\\n",
       "0        1556025919  192.168.1.32   55827.0  192.168.1.186    8586.0   tcp   \n",
       "1        1556294902  192.168.1.30   51524.0  192.168.1.195      80.0   tcp   \n",
       "2        1556025887  192.168.1.32   55428.0  192.168.1.195    1314.0   tcp   \n",
       "3        1556079325  192.168.1.31   58876.0  192.168.1.195     513.0   tcp   \n",
       "4        1556021906  192.168.1.32   53925.0  192.168.1.133    5950.0   tcp   \n",
       "...             ...           ...       ...            ...       ...   ...   \n",
       "2271715  1556429194  192.168.1.37   38131.0  192.168.1.193     445.0   tcp   \n",
       "2271716  1556429475  192.168.1.37   44413.0    13.55.50.68     123.0   udp   \n",
       "2271717  1556429477  192.168.1.33   39296.0  203.14.129.10     123.0   udp   \n",
       "2271718  1556431523  192.168.1.37   37268.0    13.55.50.68     123.0   udp   \n",
       "2271719  1556431525  192.168.1.33   37866.0  203.14.129.10     123.0   udp   \n",
       "\n",
       "        service  duration  src_bytes  dst_bytes  ... http_response_body_len  \\\n",
       "0             -  0.000000        0.0        0.0  ...                    0.0   \n",
       "1          http  0.022213      155.0      978.0  ...                    0.0   \n",
       "2             -  0.000000        0.0        0.0  ...                    0.0   \n",
       "3             -  0.000000        0.0        0.0  ...                    0.0   \n",
       "4             -  0.000000        0.0        0.0  ...                    0.0   \n",
       "...         ...       ...        ...        ...  ...                    ...   \n",
       "2271715       -  0.000029        0.0        0.0  ...                    0.0   \n",
       "2271716       -  0.012730       48.0       48.0  ...                    0.0   \n",
       "2271717       -  0.032825       48.0       48.0  ...                    0.0   \n",
       "2271718       -  0.012950       48.0       48.0  ...                    0.0   \n",
       "2271719       -  0.034296       48.0       48.0  ...                    0.0   \n",
       "\n",
       "         http_status_code  http_user_agent  http_orig_mime_types  \\\n",
       "0                     0.0                -                     -   \n",
       "1                     0.0                -                     -   \n",
       "2                     0.0                -                     -   \n",
       "3                     0.0                -                     -   \n",
       "4                     0.0                -                     -   \n",
       "...                   ...              ...                   ...   \n",
       "2271715               0.0                -                     -   \n",
       "2271716               0.0                -                     -   \n",
       "2271717               0.0                -                     -   \n",
       "2271718               0.0                -                     -   \n",
       "2271719               0.0                -                     -   \n",
       "\n",
       "         http_resp_mime_types  weird_name weird_addl  weird_notice  label  \\\n",
       "0                           -           -          -             -    1.0   \n",
       "1                           -           -          -             -    1.0   \n",
       "2                           -           -          -             -    1.0   \n",
       "3                           -           -          -             -    1.0   \n",
       "4                           -           -          -             -    1.0   \n",
       "...                       ...         ...        ...           ...    ...   \n",
       "2271715                     -           -          -             -    1.0   \n",
       "2271716                     -           -          -             -    1.0   \n",
       "2271717                     -           -          -             -    1.0   \n",
       "2271718                     -           -          -             -    1.0   \n",
       "2271719                     -           -          -             -    1.0   \n",
       "\n",
       "               type  \n",
       "0          scanning  \n",
       "1          password  \n",
       "2          scanning  \n",
       "3          scanning  \n",
       "4          scanning  \n",
       "...             ...  \n",
       "2271715  ransomware  \n",
       "2271716  ransomware  \n",
       "2271717  ransomware  \n",
       "2271718  ransomware  \n",
       "2271719  ransomware  \n",
       "\n",
       "[2271720 rows x 45 columns]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['src_ip'] = data.src_ip.apply(lambda x: socket.inet_ntoa(struct.pack('>I', random.randint(0xac100001, 0xac1f0001))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['src_ip'] = data.src_ip.apply(str)\n",
    "data['src_port'] = data.src_port.apply(str)\n",
    "data['dst_ip'] = data.dst_ip.apply(str)\n",
    "data['dst_port'] = data.dst_port.apply(str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['src_ip'] = data['src_ip'] + ':' + data['src_port']\n",
    "data['dst_ip'] = data['dst_ip'] + ':' + data['dst_port']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "scanning      714995\n",
       "ddos          616039\n",
       "dos           337072\n",
       "xss           211184\n",
       "password      135923\n",
       "ransomware     80109\n",
       "normal         78955\n",
       "backdoor       50893\n",
       "injection      45396\n",
       "mitm            1154\n",
       "Name: type, dtype: int64"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.type.value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['-', '1', '2', '4', '6', '7', '9'], dtype=object)"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data['http_trans_depth'].unique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.drop(columns=['ts','src_port','dst_port','http_uri','weird_name','weird_addl','weird_notice','dns_query','ssl_subject','ssl_issuer','http_user_agent','label'],inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.rename(columns={\"type\": \"label\"},inplace = True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "le = LabelEncoder()\n",
    "le.fit(data.label.values)\n",
    "data['label'] = le.transform(data['label'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "label = data.label"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.drop(columns=['label'],inplace = True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "scaler = StandardScaler()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "data =  pd.concat([data, label], axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train, X_test, y_train, y_test = train_test_split(\n",
    "     data, label, test_size=0.3, random_state=123,stratify= label)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>src_ip</th>\n",
       "      <th>dst_ip</th>\n",
       "      <th>proto</th>\n",
       "      <th>service</th>\n",
       "      <th>duration</th>\n",
       "      <th>src_bytes</th>\n",
       "      <th>dst_bytes</th>\n",
       "      <th>conn_state</th>\n",
       "      <th>missed_bytes</th>\n",
       "      <th>src_pkts</th>\n",
       "      <th>...</th>\n",
       "      <th>ssl_established</th>\n",
       "      <th>http_trans_depth</th>\n",
       "      <th>http_method</th>\n",
       "      <th>http_version</th>\n",
       "      <th>http_request_body_len</th>\n",
       "      <th>http_response_body_len</th>\n",
       "      <th>http_status_code</th>\n",
       "      <th>http_orig_mime_types</th>\n",
       "      <th>http_resp_mime_types</th>\n",
       "      <th>label</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1220102</th>\n",
       "      <td>172.30.169.94:42256.0</td>\n",
       "      <td>192.168.1.184:443.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000003</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>SHR</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1486264</th>\n",
       "      <td>172.29.252.92:7845.0</td>\n",
       "      <td>192.168.1.180:45999.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>S0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17089</th>\n",
       "      <td>172.27.150.106:55218.0</td>\n",
       "      <td>192.168.1.190:80.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000260</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>S1</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>570758</th>\n",
       "      <td>172.19.0.24:58775.0</td>\n",
       "      <td>192.168.1.250:20222.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>S0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2006894</th>\n",
       "      <td>172.21.225.127:38344.0</td>\n",
       "      <td>192.168.1.184:80.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>http</td>\n",
       "      <td>0.009098</td>\n",
       "      <td>152.0</td>\n",
       "      <td>171.0</td>\n",
       "      <td>SF</td>\n",
       "      <td>0.0</td>\n",
       "      <td>6.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1684689</th>\n",
       "      <td>172.27.159.225:55830.0</td>\n",
       "      <td>192.168.1.1:53.0</td>\n",
       "      <td>udp</td>\n",
       "      <td>dns</td>\n",
       "      <td>0.002090</td>\n",
       "      <td>39.0</td>\n",
       "      <td>39.0</td>\n",
       "      <td>SF</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6356</th>\n",
       "      <td>172.23.222.170:44741.0</td>\n",
       "      <td>192.168.1.133:4242.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>S0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>338212</th>\n",
       "      <td>172.22.77.121:54390.0</td>\n",
       "      <td>192.168.1.152:80.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>http</td>\n",
       "      <td>0.001335</td>\n",
       "      <td>153.0</td>\n",
       "      <td>463.0</td>\n",
       "      <td>SF</td>\n",
       "      <td>0.0</td>\n",
       "      <td>5.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2033037</th>\n",
       "      <td>172.21.152.99:60584.0</td>\n",
       "      <td>192.168.1.33:80.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000097</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>REJ</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1691452</th>\n",
       "      <td>172.16.198.55:22542.0</td>\n",
       "      <td>192.168.1.180:49258.0</td>\n",
       "      <td>tcp</td>\n",
       "      <td>-</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>S0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>...</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-</td>\n",
       "      <td>-</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>1590204 rows × 33 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                         src_ip                 dst_ip proto service  \\\n",
       "1220102   172.30.169.94:42256.0    192.168.1.184:443.0   tcp       -   \n",
       "1486264    172.29.252.92:7845.0  192.168.1.180:45999.0   tcp       -   \n",
       "17089    172.27.150.106:55218.0     192.168.1.190:80.0   tcp       -   \n",
       "570758      172.19.0.24:58775.0  192.168.1.250:20222.0   tcp       -   \n",
       "2006894  172.21.225.127:38344.0     192.168.1.184:80.0   tcp    http   \n",
       "...                         ...                    ...   ...     ...   \n",
       "1684689  172.27.159.225:55830.0       192.168.1.1:53.0   udp     dns   \n",
       "6356     172.23.222.170:44741.0   192.168.1.133:4242.0   tcp       -   \n",
       "338212    172.22.77.121:54390.0     192.168.1.152:80.0   tcp    http   \n",
       "2033037   172.21.152.99:60584.0      192.168.1.33:80.0   tcp       -   \n",
       "1691452   172.16.198.55:22542.0  192.168.1.180:49258.0   tcp       -   \n",
       "\n",
       "         duration  src_bytes  dst_bytes conn_state  missed_bytes  src_pkts  \\\n",
       "1220102  0.000003        0.0        0.0        SHR           0.0       1.0   \n",
       "1486264  0.000000        0.0        0.0         S0           0.0       1.0   \n",
       "17089    0.000260        0.0        0.0         S1           0.0       2.0   \n",
       "570758   0.000000        0.0        0.0         S0           0.0       1.0   \n",
       "2006894  0.009098      152.0      171.0         SF           0.0       6.0   \n",
       "...           ...        ...        ...        ...           ...       ...   \n",
       "1684689  0.002090       39.0       39.0         SF           0.0       1.0   \n",
       "6356     0.000000        0.0        0.0         S0           0.0       1.0   \n",
       "338212   0.001335      153.0      463.0         SF           0.0       5.0   \n",
       "2033037  0.000097        0.0        0.0        REJ           0.0       1.0   \n",
       "1691452  0.000000        0.0        0.0         S0           0.0       1.0   \n",
       "\n",
       "         ...  ssl_established  http_trans_depth  http_method  http_version  \\\n",
       "1220102  ...                -                 -            -             -   \n",
       "1486264  ...                -                 -            -             -   \n",
       "17089    ...                -                 -            -             -   \n",
       "570758   ...                -                 -            -             -   \n",
       "2006894  ...                -                 -            -             -   \n",
       "...      ...              ...               ...          ...           ...   \n",
       "1684689  ...                -                 -            -             -   \n",
       "6356     ...                -                 -            -             -   \n",
       "338212   ...                -                 -            -             -   \n",
       "2033037  ...                -                 -            -             -   \n",
       "1691452  ...                -                 -            -             -   \n",
       "\n",
       "         http_request_body_len  http_response_body_len http_status_code  \\\n",
       "1220102                    0.0                     0.0              0.0   \n",
       "1486264                    0.0                     0.0              0.0   \n",
       "17089                      0.0                     0.0              0.0   \n",
       "570758                     0.0                     0.0              0.0   \n",
       "2006894                    0.0                     0.0              0.0   \n",
       "...                        ...                     ...              ...   \n",
       "1684689                    0.0                     0.0              0.0   \n",
       "6356                       0.0                     0.0              0.0   \n",
       "338212                     0.0                     0.0              0.0   \n",
       "2033037                    0.0                     0.0              0.0   \n",
       "1691452                    0.0                     0.0              0.0   \n",
       "\n",
       "        http_orig_mime_types http_resp_mime_types label  \n",
       "1220102                    -                    -     1  \n",
       "1486264                    -                    -     8  \n",
       "17089                      -                    -     1  \n",
       "570758                     -                    -     8  \n",
       "2006894                    -                    -     1  \n",
       "...                      ...                  ...   ...  \n",
       "1684689                    -                    -     1  \n",
       "6356                       -                    -     8  \n",
       "338212                     -                    -     6  \n",
       "2033037                    -                    -     0  \n",
       "1691452                    -                    -     8  \n",
       "\n",
       "[1590204 rows x 33 columns]"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "encoder = ce.TargetEncoder(cols=['proto','service','conn_state','dns_qclass','dns_qtype','dns_rcode','dns_AA','dns_RD','dns_RA','dns_rejected','ssl_version','ssl_cipher','ssl_resumed','ssl_established','http_method','http_version','http_status_code','http_orig_mime_types','http_resp_mime_types','http_trans_depth'])\n",
    "encoder.fit(X_train, y_train)\n",
    "X_train = encoder.transform(X_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [],
   "source": [
    "cols_to_norm = list(set(list(X_train.iloc[:, 2:].columns ))  - set(list(['label'])) )\n",
    "X_train[cols_to_norm] = scaler.fit_transform(X_train[cols_to_norm])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train['h'] = X_train[ cols_to_norm ].values.tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>src_ip</th>\n",
       "      <th>dst_ip</th>\n",
       "      <th>proto</th>\n",
       "      <th>service</th>\n",
       "      <th>duration</th>\n",
       "      <th>src_bytes</th>\n",
       "      <th>dst_bytes</th>\n",
       "      <th>conn_state</th>\n",
       "      <th>missed_bytes</th>\n",
       "      <th>src_pkts</th>\n",
       "      <th>...</th>\n",
       "      <th>http_trans_depth</th>\n",
       "      <th>http_method</th>\n",
       "      <th>http_version</th>\n",
       "      <th>http_request_body_len</th>\n",
       "      <th>http_response_body_len</th>\n",
       "      <th>http_status_code</th>\n",
       "      <th>http_orig_mime_types</th>\n",
       "      <th>http_resp_mime_types</th>\n",
       "      <th>label</th>\n",
       "      <th>h</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1220102</th>\n",
       "      <td>172.30.169.94:42256.0</td>\n",
       "      <td>192.168.1.184:443.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086422</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>-1.370432</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>1</td>\n",
       "      <td>[0.031656479263249236, -0.010544215749821386, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1486264</th>\n",
       "      <td>172.29.252.92:7845.0</td>\n",
       "      <td>192.168.1.180:45999.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086422</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>1.205621</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>8</td>\n",
       "      <td>[0.031656479263249236, -0.010654428878323154, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17089</th>\n",
       "      <td>172.27.150.106:55218.0</td>\n",
       "      <td>192.168.1.190:80.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086419</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>-1.518812</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.011864</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>1</td>\n",
       "      <td>[0.031656479263249236, -0.008891018822294875, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>570758</th>\n",
       "      <td>172.19.0.24:58775.0</td>\n",
       "      <td>192.168.1.250:20222.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086422</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>1.205621</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>8</td>\n",
       "      <td>[0.031656479263249236, -0.010764642006824922, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2006894</th>\n",
       "      <td>172.21.225.127:38344.0</td>\n",
       "      <td>192.168.1.184:80.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>2.202699</td>\n",
       "      <td>-0.086330</td>\n",
       "      <td>-0.026782</td>\n",
       "      <td>-0.022969</td>\n",
       "      <td>0.500845</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>0.008678</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>1</td>\n",
       "      <td>[0.031656479263249236, 0.0010281627428641899, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1684689</th>\n",
       "      <td>172.27.159.225:55830.0</td>\n",
       "      <td>192.168.1.1:53.0</td>\n",
       "      <td>1.404392</td>\n",
       "      <td>0.040903</td>\n",
       "      <td>-0.086401</td>\n",
       "      <td>-0.026785</td>\n",
       "      <td>-0.022973</td>\n",
       "      <td>0.500845</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>1</td>\n",
       "      <td>[0.031656479263249236, -0.010130916517939759, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6356</th>\n",
       "      <td>172.23.222.170:44741.0</td>\n",
       "      <td>192.168.1.133:4242.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086422</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>1.205621</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>8</td>\n",
       "      <td>[0.031656479263249236, -0.010764642006824922, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>338212</th>\n",
       "      <td>172.22.77.121:54390.0</td>\n",
       "      <td>192.168.1.152:80.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>2.202699</td>\n",
       "      <td>-0.086408</td>\n",
       "      <td>-0.026782</td>\n",
       "      <td>-0.022961</td>\n",
       "      <td>0.500845</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>0.003542</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>6</td>\n",
       "      <td>[0.031656479263249236, -0.00037705464553334443...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2033037</th>\n",
       "      <td>172.21.152.99:60584.0</td>\n",
       "      <td>192.168.1.33:80.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086421</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>-0.412740</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>0</td>\n",
       "      <td>[0.031656479263249236, -0.010654428878323154, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1691452</th>\n",
       "      <td>172.16.198.55:22542.0</td>\n",
       "      <td>192.168.1.180:49258.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086422</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>1.205621</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>8</td>\n",
       "      <td>[0.031656479263249236, -0.010654428878323154, ...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>1590204 rows × 34 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                         src_ip                 dst_ip     proto   service  \\\n",
       "1220102   172.30.169.94:42256.0    192.168.1.184:443.0 -0.141989 -0.326613   \n",
       "1486264    172.29.252.92:7845.0  192.168.1.180:45999.0 -0.141989 -0.326613   \n",
       "17089    172.27.150.106:55218.0     192.168.1.190:80.0 -0.141989 -0.326613   \n",
       "570758      172.19.0.24:58775.0  192.168.1.250:20222.0 -0.141989 -0.326613   \n",
       "2006894  172.21.225.127:38344.0     192.168.1.184:80.0 -0.141989  2.202699   \n",
       "...                         ...                    ...       ...       ...   \n",
       "1684689  172.27.159.225:55830.0       192.168.1.1:53.0  1.404392  0.040903   \n",
       "6356     172.23.222.170:44741.0   192.168.1.133:4242.0 -0.141989 -0.326613   \n",
       "338212    172.22.77.121:54390.0     192.168.1.152:80.0 -0.141989  2.202699   \n",
       "2033037   172.21.152.99:60584.0      192.168.1.33:80.0 -0.141989 -0.326613   \n",
       "1691452   172.16.198.55:22542.0  192.168.1.180:49258.0 -0.141989 -0.326613   \n",
       "\n",
       "         duration  src_bytes  dst_bytes  conn_state  missed_bytes  src_pkts  \\\n",
       "1220102 -0.086422  -0.026786  -0.022974   -1.370432     -0.007051 -0.017000   \n",
       "1486264 -0.086422  -0.026786  -0.022974    1.205621     -0.007051 -0.017000   \n",
       "17089   -0.086419  -0.026786  -0.022974   -1.518812     -0.007051 -0.011864   \n",
       "570758  -0.086422  -0.026786  -0.022974    1.205621     -0.007051 -0.017000   \n",
       "2006894 -0.086330  -0.026782  -0.022969    0.500845     -0.007051  0.008678   \n",
       "...           ...        ...        ...         ...           ...       ...   \n",
       "1684689 -0.086401  -0.026785  -0.022973    0.500845     -0.007051 -0.017000   \n",
       "6356    -0.086422  -0.026786  -0.022974    1.205621     -0.007051 -0.017000   \n",
       "338212  -0.086408  -0.026782  -0.022961    0.500845     -0.007051  0.003542   \n",
       "2033037 -0.086421  -0.026786  -0.022974   -0.412740     -0.007051 -0.017000   \n",
       "1691452 -0.086422  -0.026786  -0.022974    1.205621     -0.007051 -0.017000   \n",
       "\n",
       "         ...  http_trans_depth  http_method  http_version  \\\n",
       "1220102  ...          0.032008     0.030573      0.031656   \n",
       "1486264  ...          0.032008     0.030573      0.031656   \n",
       "17089    ...          0.032008     0.030573      0.031656   \n",
       "570758   ...          0.032008     0.030573      0.031656   \n",
       "2006894  ...          0.032008     0.030573      0.031656   \n",
       "...      ...               ...          ...           ...   \n",
       "1684689  ...          0.032008     0.030573      0.031656   \n",
       "6356     ...          0.032008     0.030573      0.031656   \n",
       "338212   ...          0.032008     0.030573      0.031656   \n",
       "2033037  ...          0.032008     0.030573      0.031656   \n",
       "1691452  ...          0.032008     0.030573      0.031656   \n",
       "\n",
       "         http_request_body_len  http_response_body_len  http_status_code  \\\n",
       "1220102              -0.002745                -0.00124          0.025943   \n",
       "1486264              -0.002745                -0.00124          0.025943   \n",
       "17089                -0.002745                -0.00124          0.025943   \n",
       "570758               -0.002745                -0.00124          0.025943   \n",
       "2006894              -0.002745                -0.00124          0.025943   \n",
       "...                        ...                     ...               ...   \n",
       "1684689              -0.002745                -0.00124          0.025943   \n",
       "6356                 -0.002745                -0.00124          0.025943   \n",
       "338212               -0.002745                -0.00124          0.025943   \n",
       "2033037              -0.002745                -0.00124          0.025943   \n",
       "1691452              -0.002745                -0.00124          0.025943   \n",
       "\n",
       "         http_orig_mime_types  http_resp_mime_types  label  \\\n",
       "1220102             -0.008069             -0.014919      1   \n",
       "1486264             -0.008069             -0.014919      8   \n",
       "17089               -0.008069             -0.014919      1   \n",
       "570758              -0.008069             -0.014919      8   \n",
       "2006894             -0.008069             -0.014919      1   \n",
       "...                       ...                   ...    ...   \n",
       "1684689             -0.008069             -0.014919      1   \n",
       "6356                -0.008069             -0.014919      8   \n",
       "338212              -0.008069             -0.014919      6   \n",
       "2033037             -0.008069             -0.014919      0   \n",
       "1691452             -0.008069             -0.014919      8   \n",
       "\n",
       "                                                         h  \n",
       "1220102  [0.031656479263249236, -0.010544215749821386, ...  \n",
       "1486264  [0.031656479263249236, -0.010654428878323154, ...  \n",
       "17089    [0.031656479263249236, -0.008891018822294875, ...  \n",
       "570758   [0.031656479263249236, -0.010764642006824922, ...  \n",
       "2006894  [0.031656479263249236, 0.0010281627428641899, ...  \n",
       "...                                                    ...  \n",
       "1684689  [0.031656479263249236, -0.010130916517939759, ...  \n",
       "6356     [0.031656479263249236, -0.010764642006824922, ...  \n",
       "338212   [0.031656479263249236, -0.00037705464553334443...  \n",
       "2033037  [0.031656479263249236, -0.010654428878323154, ...  \n",
       "1691452  [0.031656479263249236, -0.010654428878323154, ...  \n",
       "\n",
       "[1590204 rows x 34 columns]"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [],
   "source": [
    "G = nx.from_pandas_edgelist(X_train, \"src_ip\", \"dst_ip\", ['h','label'],create_using=nx.MultiGraph())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [],
   "source": [
    "G = G.to_directed()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [],
   "source": [
    "G = from_networkx(G,edge_attrs=['h','label'] )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Eq1\n",
    "G.ndata['h'] = th.ones(G.num_nodes(), G.edata['h'].shape[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [],
   "source": [
    "G.ndata['h'] = th.reshape(G.ndata['h'], (G.ndata['h'].shape[0], 1,G.ndata['h'].shape[1]))\n",
    "G.edata['h'] = th.reshape(G.edata['h'], (G.edata['h'].shape[0], 1,G.edata['h'].shape[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [],
   "source": [
    "G.edata['train_mask'] = th.ones(len(G.edata['h']), dtype=th.bool)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Model(nn.Module):\n",
    "    def __init__(self, ndim_in, ndim_out, edim, activation, dropout):\n",
    "        super().__init__()\n",
    "        self.gnn = SAGE(ndim_in, ndim_out, edim, activation, dropout)\n",
    "        self.pred = MLPPredictor(ndim_out, 10)\n",
    "    def forward(self, g, nfeats, efeats):\n",
    "        h = self.gnn(g, nfeats, efeats)\n",
    "        return self.pred(g, h)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [],
   "source": [
    "class SAGELayer(nn.Module):\n",
    "    def __init__(self, ndim_in, edims, ndim_out, activation):\n",
    "        super(SAGELayer, self).__init__()\n",
    "        ### force to outut fix dimensions\n",
    "        self.W_msg = nn.Linear(ndim_in + edims, ndim_out)\n",
    "        ### apply weight\n",
    "        self.W_apply = nn.Linear(ndim_in + ndim_out, ndim_out)\n",
    "        self.activation = activation\n",
    "\n",
    "    def message_func(self, edges):\n",
    "        return {'m': self.W_msg(th.cat([edges.src['h'], edges.data['h']], 2))}\n",
    "\n",
    "    def forward(self, g_dgl, nfeats, efeats):\n",
    "        with g_dgl.local_scope():\n",
    "            g = g_dgl\n",
    "            g.ndata['h'] = nfeats\n",
    "            g.edata['h'] = efeats\n",
    "            # Eq4\n",
    "            g.update_all(self.message_func, fn.mean('m', 'h_neigh'))\n",
    "            # Eq5          \n",
    "            g.ndata['h'] = F.relu(self.W_apply(th.cat([g.ndata['h'], g.ndata['h_neigh']], 2)))\n",
    "            return g.ndata['h']\n",
    "\n",
    "\n",
    "class SAGE(nn.Module):\n",
    "    def __init__(self, ndim_in, ndim_out, edim, activation, dropout):\n",
    "        super(SAGE, self).__init__()\n",
    "        self.layers = nn.ModuleList()\n",
    "        self.layers.append(SAGELayer(ndim_in, edim, 128, activation))\n",
    "        self.layers.append(SAGELayer(128, edim, ndim_out, activation))\n",
    "        self.dropout = nn.Dropout(p=dropout)\n",
    "\n",
    "    def forward(self, g, nfeats, efeats):\n",
    "        for i, layer in enumerate(self.layers):\n",
    "            if i != 0:\n",
    "                nfeats = self.dropout(nfeats)\n",
    "            nfeats = layer(g, nfeats, efeats)\n",
    "        return nfeats.sum(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [],
   "source": [
    "class MLPPredictor(nn.Module):\n",
    "    def __init__(self, in_features, out_classes):\n",
    "        super().__init__()\n",
    "        self.W = nn.Linear(in_features * 2, out_classes)\n",
    "\n",
    "    def apply_edges(self, edges):\n",
    "        h_u = edges.src['h']\n",
    "        h_v = edges.dst['h']\n",
    "        score = self.W(th.cat([h_u, h_v], 1))\n",
    "        return {'score': score}\n",
    "\n",
    "    def forward(self, graph, h):\n",
    "        with graph.local_scope():\n",
    "            graph.ndata['h'] = h\n",
    "            graph.apply_edges(self.apply_edges)\n",
    "            return graph.edata['score']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cuda', index=0)"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "G = G.to('cuda:0')\n",
    "G.device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cuda', index=0)"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "G.ndata['h'].device\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cuda', index=0)"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "G.edata['h'].device\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.utils import class_weight\n",
    "class_weights = class_weight.compute_class_weight('balanced',\n",
    "                                                 np.unique(G.edata['label'].cpu().numpy()),\n",
    "                                                 G.edata['label'].cpu().numpy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [],
   "source": [
    "class_weights = th.FloatTensor(class_weights).cuda()\n",
    "criterion = nn.CrossEntropyLoss(weight = class_weights)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_accuracy(pred, labels):\n",
    "    return (pred.argmax(1) == labels).float().mean().item()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 100  Training acc: 0.5622228384017944\n",
      "Epoch: 200  Training acc: 0.698897123336792\n",
      "Epoch: 300  Training acc: 0.7005963325500488\n",
      "Epoch: 400  Training acc: 0.7232459187507629\n",
      "Epoch: 500  Training acc: 0.7733508348464966\n",
      "Epoch: 600  Training acc: 0.7604178786277771\n",
      "Epoch: 700  Training acc: 0.7459869980812073\n",
      "Epoch: 800  Training acc: 0.7555640935897827\n",
      "Epoch: 900  Training acc: 0.7852099537849426\n",
      "Epoch: 1000  Training acc: 0.7912085652351379\n",
      "Epoch: 1100  Training acc: 0.7631102800369263\n",
      "Epoch: 1200  Training acc: 0.7781992554664612\n",
      "Epoch: 1300  Training acc: 0.7793076038360596\n",
      "Epoch: 1400  Training acc: 0.8022056221961975\n",
      "Epoch: 1500  Training acc: 0.7667208313941956\n",
      "Epoch: 1600  Training acc: 0.7944477796554565\n",
      "Epoch: 1700  Training acc: 0.8050265908241272\n",
      "Epoch: 1800  Training acc: 0.8065757751464844\n",
      "Epoch: 1900  Training acc: 0.800061821937561\n",
      "Epoch: 2000  Training acc: 0.8021285533905029\n",
      "Epoch: 2100  Training acc: 0.8087337017059326\n",
      "Epoch: 2200  Training acc: 0.8202875256538391\n",
      "Epoch: 2300  Training acc: 0.7861010432243347\n",
      "Epoch: 2400  Training acc: 0.7900285720825195\n",
      "Epoch: 2500  Training acc: 0.7903112173080444\n",
      "Epoch: 2600  Training acc: 0.8078611493110657\n",
      "Epoch: 2700  Training acc: 0.8263550400733948\n",
      "Epoch: 2800  Training acc: 0.8006259202957153\n",
      "Epoch: 2900  Training acc: 0.8319747447967529\n",
      "Epoch: 3000  Training acc: 0.8206133246421814\n",
      "Epoch: 3100  Training acc: 0.8068540692329407\n",
      "Epoch: 3200  Training acc: 0.7992047071456909\n",
      "Epoch: 3300  Training acc: 0.8310163617134094\n",
      "Epoch: 3400  Training acc: 0.8226831555366516\n",
      "Epoch: 3500  Training acc: 0.8205142617225647\n",
      "Epoch: 3600  Training acc: 0.8489373326301575\n",
      "Epoch: 3700  Training acc: 0.823835551738739\n",
      "Epoch: 3800  Training acc: 0.8102400898933411\n",
      "Epoch: 3900  Training acc: 0.8411113023757935\n",
      "Epoch: 4000  Training acc: 0.836643636226654\n",
      "Epoch: 4100  Training acc: 0.8317911028862\n",
      "Epoch: 4200  Training acc: 0.831445574760437\n",
      "Epoch: 4300  Training acc: 0.8453255295753479\n",
      "Epoch: 4400  Training acc: 0.8471306562423706\n",
      "Epoch: 4500  Training acc: 0.8500692844390869\n",
      "Epoch: 4600  Training acc: 0.8496441841125488\n",
      "Epoch: 4700  Training acc: 0.8447762131690979\n",
      "Epoch: 4800  Training acc: 0.8399602174758911\n",
      "Epoch: 4900  Training acc: 0.852260172367096\n",
      "Epoch: 5000  Training acc: 0.8460817337036133\n",
      "Epoch: 5100  Training acc: 0.8392457962036133\n",
      "Epoch: 5200  Training acc: 0.8527271151542664\n",
      "Epoch: 5300  Training acc: 0.8541193604469299\n",
      "Epoch: 5400  Training acc: 0.818974494934082\n",
      "Epoch: 5500  Training acc: 0.8591684103012085\n",
      "Epoch: 5600  Training acc: 0.8172558546066284\n",
      "Epoch: 5700  Training acc: 0.8582364320755005\n",
      "Epoch: 5800  Training acc: 0.8329145312309265\n",
      "Epoch: 5900  Training acc: 0.8546935319900513\n",
      "Epoch: 6000  Training acc: 0.8269851207733154\n",
      "Epoch: 6100  Training acc: 0.8604670166969299\n",
      "Epoch: 6200  Training acc: 0.8569815754890442\n",
      "Epoch: 6300  Training acc: 0.8505399823188782\n",
      "Epoch: 6400  Training acc: 0.8474095463752747\n",
      "Epoch: 6500  Training acc: 0.858339250087738\n",
      "Epoch: 6600  Training acc: 0.8574349880218506\n",
      "Epoch: 6700  Training acc: 0.83979731798172\n",
      "Epoch: 6800  Training acc: 0.8438584208488464\n",
      "Epoch: 6900  Training acc: 0.8630147576332092\n",
      "Epoch: 7000  Training acc: 0.8513524532318115\n",
      "Epoch: 7100  Training acc: 0.8611671924591064\n",
      "Epoch: 7200  Training acc: 0.8589165806770325\n",
      "Epoch: 7300  Training acc: 0.8607923984527588\n",
      "Epoch: 7400  Training acc: 0.8464184999465942\n",
      "Epoch: 7500  Training acc: 0.861613392829895\n",
      "Epoch: 7600  Training acc: 0.8506003618240356\n",
      "Epoch: 7700  Training acc: 0.8675158023834229\n",
      "Epoch: 7800  Training acc: 0.8679304718971252\n",
      "Epoch: 7900  Training acc: 0.857218325138092\n",
      "Epoch: 8000  Training acc: 0.8670067191123962\n",
      "Epoch: 8100  Training acc: 0.8667158484458923\n",
      "Epoch: 8200  Training acc: 0.867386519908905\n",
      "Epoch: 8300  Training acc: 0.8548755645751953\n",
      "Epoch: 8400  Training acc: 0.8734970688819885\n",
      "Epoch: 8500  Training acc: 0.8765529990196228\n",
      "Epoch: 8600  Training acc: 0.855668842792511\n",
      "Epoch: 8700  Training acc: 0.8775619864463806\n",
      "Epoch: 8800  Training acc: 0.862970769405365\n",
      "Epoch: 8900  Training acc: 0.8443939089775085\n",
      "Epoch: 9000  Training acc: 0.8771239519119263\n",
      "Epoch: 9100  Training acc: 0.8527749180793762\n",
      "Epoch: 9200  Training acc: 0.8704537749290466\n",
      "Epoch: 9300  Training acc: 0.867680549621582\n",
      "Epoch: 9400  Training acc: 0.8673151731491089\n",
      "Epoch: 9500  Training acc: 0.8747441172599792\n",
      "Epoch: 9600  Training acc: 0.8599004149436951\n",
      "Epoch: 9700  Training acc: 0.8665237426757812\n",
      "Epoch: 9800  Training acc: 0.8786348104476929\n",
      "Epoch: 9900  Training acc: 0.8317486643791199\n",
      "Epoch: 10000  Training acc: 0.8805732131004333\n",
      "Epoch: 10100  Training acc: 0.8769994378089905\n",
      "Epoch: 10200  Training acc: 0.8697126507759094\n",
      "Epoch: 10300  Training acc: 0.8802782893180847\n",
      "Epoch: 10400  Training acc: 0.8811134099960327\n",
      "Epoch: 10500  Training acc: 0.8776581883430481\n",
      "Epoch: 10600  Training acc: 0.8749613761901855\n",
      "Epoch: 10700  Training acc: 0.8514974117279053\n",
      "Epoch: 10800  Training acc: 0.8664684295654297\n",
      "Epoch: 10900  Training acc: 0.8807995915412903\n",
      "Epoch: 11000  Training acc: 0.8713127970695496\n",
      "Epoch: 11100  Training acc: 0.8746170401573181\n",
      "Epoch: 11200  Training acc: 0.8685285449028015\n",
      "Epoch: 11300  Training acc: 0.8808549642562866\n",
      "Epoch: 11400  Training acc: 0.8620390892028809\n",
      "Epoch: 11500  Training acc: 0.8776383996009827\n",
      "Epoch: 11600  Training acc: 0.8637206554412842\n",
      "Epoch: 11700  Training acc: 0.8637851476669312\n",
      "Epoch: 11800  Training acc: 0.8857024312019348\n",
      "Epoch: 11900  Training acc: 0.8784131407737732\n",
      "Epoch: 12000  Training acc: 0.8438943028450012\n",
      "Epoch: 12100  Training acc: 0.8792966604232788\n",
      "Epoch: 12200  Training acc: 0.8758703470230103\n",
      "Epoch: 12300  Training acc: 0.8795607686042786\n",
      "Epoch: 12400  Training acc: 0.8759093284606934\n",
      "Epoch: 12500  Training acc: 0.8792803287506104\n",
      "Epoch: 12600  Training acc: 0.853690505027771\n",
      "Epoch: 12700  Training acc: 0.8822075724601746\n",
      "Epoch: 12800  Training acc: 0.8651245832443237\n",
      "Epoch: 12900  Training acc: 0.8636496067047119\n",
      "Epoch: 13000  Training acc: 0.8767196536064148\n",
      "Epoch: 13100  Training acc: 0.8753106594085693\n",
      "Epoch: 13200  Training acc: 0.8851370811462402\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-81-ec94f4d9c55b>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mepoch\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m15000\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0mpred\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mG\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnode_features\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0medge_features\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcuda\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m     \u001b[0mloss\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcriterion\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpred\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mtrain_mask\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m,\u001b[0m\u001b[0medge_label\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mtrain_mask\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m     \u001b[0mopt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzero_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/lib/python3/dist-packages/torch/nn/modules/module.py\u001b[0m in \u001b[0;36m_call_impl\u001b[0;34m(self, *input, **kwargs)\u001b[0m\n\u001b[1;32m    720\u001b[0m             \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_slow_forward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    721\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 722\u001b[0;31m             \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mforward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    723\u001b[0m         for hook in itertools.chain(\n\u001b[1;32m    724\u001b[0m                 \u001b[0m_global_forward_hooks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-71-90baa6f0d098>\u001b[0m in \u001b[0;36mforward\u001b[0;34m(self, g, nfeats, efeats)\u001b[0m\n\u001b[1;32m      5\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpred\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mMLPPredictor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mndim_out\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mforward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnfeats\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mefeats\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m         \u001b[0mh\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgnn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnfeats\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mefeats\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      8\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpred\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mh\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/lib/python3/dist-packages/torch/nn/modules/module.py\u001b[0m in \u001b[0;36m_call_impl\u001b[0;34m(self, *input, **kwargs)\u001b[0m\n\u001b[1;32m    720\u001b[0m             \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_slow_forward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    721\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 722\u001b[0;31m             \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mforward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    723\u001b[0m         for hook in itertools.chain(\n\u001b[1;32m    724\u001b[0m                 \u001b[0m_global_forward_hooks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-72-efdb008b3895>\u001b[0m in \u001b[0;36mforward\u001b[0;34m(self, g, nfeats, efeats)\u001b[0m\n\u001b[1;32m     30\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0mi\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     31\u001b[0m                 \u001b[0mnfeats\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdropout\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnfeats\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 32\u001b[0;31m             \u001b[0mnfeats\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlayer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnfeats\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mefeats\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     33\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mnfeats\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/lib/python3/dist-packages/torch/nn/modules/module.py\u001b[0m in \u001b[0;36m_call_impl\u001b[0;34m(self, *input, **kwargs)\u001b[0m\n\u001b[1;32m    720\u001b[0m             \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_slow_forward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    721\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 722\u001b[0;31m             \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mforward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    723\u001b[0m         for hook in itertools.chain(\n\u001b[1;32m    724\u001b[0m                 \u001b[0m_global_forward_hooks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-72-efdb008b3895>\u001b[0m in \u001b[0;36mforward\u001b[0;34m(self, g_dgl, nfeats, efeats)\u001b[0m\n\u001b[1;32m     13\u001b[0m             \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'h'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnfeats\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m             \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0medata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'h'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mefeats\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m             \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mupdate_all\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmessage_func\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'm'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'h_neigh'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     16\u001b[0m             \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'h'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mF\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrelu\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mW_apply\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mth\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'h'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'h_neigh'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     17\u001b[0m             \u001b[0;32mreturn\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'h'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/dgl/heterograph.py\u001b[0m in \u001b[0;36mupdate_all\u001b[0;34m(self, message_func, reduce_func, apply_node_func, etype)\u001b[0m\n\u001b[1;32m   4499\u001b[0m         \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtid\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_graph\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmetagraph\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfind_edge\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0metid\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   4500\u001b[0m         \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0metype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0metype\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 4501\u001b[0;31m         \u001b[0mndata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcore\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmessage_passing\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmessage_func\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreduce_func\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mapply_node_func\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   4502\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_set_n_repr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdtid\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mALL\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mndata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   4503\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/dgl/core.py\u001b[0m in \u001b[0;36mmessage_passing\u001b[0;34m(g, mfunc, rfunc, afunc)\u001b[0m\n\u001b[1;32m    293\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mis_builtin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrfunc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    294\u001b[0m             \u001b[0mmsg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmsg_field\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 295\u001b[0;31m             \u001b[0mndata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minvoke_gspmm\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcopy_e\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0medata\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmsgdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    296\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    297\u001b[0m             \u001b[0morig_nid\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdstdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mNID\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/dgl/core.py\u001b[0m in \u001b[0;36minvoke_gspmm\u001b[0;34m(graph, mfunc, rfunc, srcdata, dstdata, edata)\u001b[0m\n\u001b[1;32m    253\u001b[0m         \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0malldata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mmfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtarget\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mmfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0min_field\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    254\u001b[0m         \u001b[0mop\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mops\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'{}_{}'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 255\u001b[0;31m         \u001b[0mz\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgraph\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    256\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0mrfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mout_field\u001b[0m \u001b[0;34m:\u001b[0m \u001b[0mz\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    257\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/dgl/ops/spmm.py\u001b[0m in \u001b[0;36mfunc\u001b[0;34m(g, x)\u001b[0m\n\u001b[1;32m    170\u001b[0m             \u001b[0;32mreturn\u001b[0m \u001b[0mgspmm\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'copy_lhs'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreduce_op\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    171\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 172\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mgspmm\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'copy_rhs'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreduce_op\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    173\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    174\u001b[0m     \u001b[0mfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__name__\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/dgl/ops/spmm.py\u001b[0m in \u001b[0;36mgspmm\u001b[0;34m(g, op, reduce_op, lhs_data, rhs_data)\u001b[0m\n\u001b[1;32m     72\u001b[0m         \u001b[0mdeg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0min_degrees\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     73\u001b[0m         \u001b[0mdeg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mF\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mF\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclamp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdeg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumber_of_edges\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mF\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 74\u001b[0;31m         \u001b[0mdeg_shape\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mret_shape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mret_shape\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     75\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mret\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mF\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdeg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdeg_shape\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     76\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "node_features = G.ndata['h']\n",
    "edge_features = G.edata['h']\n",
    "\n",
    "edge_label = G.edata['label']\n",
    "train_mask = G.edata['train_mask']\n",
    "\n",
    "model = Model(G.ndata['h'].shape[2], 128, G.ndata['h'].shape[2], F.relu, 0.2).cuda()\n",
    "opt = th.optim.Adam(model.parameters())\n",
    "\n",
    "\n",
    "for epoch in range(1,15000):\n",
    "    pred = model(G, node_features,edge_features).cuda()\n",
    "    loss = criterion(pred[train_mask] ,edge_label[train_mask])\n",
    "    opt.zero_grad()\n",
    "    loss.backward()\n",
    "    opt.step()\n",
    "    if epoch % 100 == 0:\n",
    "        th.save(model.state_dict(), os.path.join('./model', 'epoch-{}.pt'.format(epoch)))\n",
    "        print('Epoch:', epoch ,' Training acc:', compute_accuracy(pred[train_mask], edge_label[train_mask]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_test = encoder.transform(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_test[cols_to_norm] = scaler.transform(X_test[cols_to_norm])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>src_ip</th>\n",
       "      <th>dst_ip</th>\n",
       "      <th>proto</th>\n",
       "      <th>service</th>\n",
       "      <th>duration</th>\n",
       "      <th>src_bytes</th>\n",
       "      <th>dst_bytes</th>\n",
       "      <th>conn_state</th>\n",
       "      <th>missed_bytes</th>\n",
       "      <th>src_pkts</th>\n",
       "      <th>...</th>\n",
       "      <th>ssl_established</th>\n",
       "      <th>http_trans_depth</th>\n",
       "      <th>http_method</th>\n",
       "      <th>http_version</th>\n",
       "      <th>http_request_body_len</th>\n",
       "      <th>http_response_body_len</th>\n",
       "      <th>http_status_code</th>\n",
       "      <th>http_orig_mime_types</th>\n",
       "      <th>http_resp_mime_types</th>\n",
       "      <th>label</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1410016</th>\n",
       "      <td>172.27.214.71:31971.0</td>\n",
       "      <td>192.168.1.46:4372.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086422</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>1.205621</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>200517</th>\n",
       "      <td>172.26.161.210:42846.0</td>\n",
       "      <td>192.168.1.184:443.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>0.525077</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>-1.533133</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.006729</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1428994</th>\n",
       "      <td>172.16.225.203:62698.0</td>\n",
       "      <td>192.168.1.169:16353.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086422</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>-0.412740</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1078536</th>\n",
       "      <td>172.19.241.97:49470.0</td>\n",
       "      <td>192.168.1.184:443.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>0.523792</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>-1.533133</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.006729</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>256376</th>\n",
       "      <td>172.20.96.45:44682.0</td>\n",
       "      <td>192.168.1.190:80.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>2.202699</td>\n",
       "      <td>-0.085307</td>\n",
       "      <td>-0.026779</td>\n",
       "      <td>-0.022920</td>\n",
       "      <td>0.500845</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>0.003542</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>507930</th>\n",
       "      <td>172.26.220.2:60854.0</td>\n",
       "      <td>192.168.1.190:80.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>2.202699</td>\n",
       "      <td>-0.081312</td>\n",
       "      <td>-0.026778</td>\n",
       "      <td>-0.022920</td>\n",
       "      <td>-1.518812</td>\n",
       "      <td>-0.007007</td>\n",
       "      <td>-0.006729</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1739336</th>\n",
       "      <td>172.17.44.1:4635.0</td>\n",
       "      <td>192.168.1.152:4635.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086420</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>-0.412740</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>347110</th>\n",
       "      <td>172.28.144.97:60159.0</td>\n",
       "      <td>192.168.1.190:12201.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086420</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>-0.412740</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6363</th>\n",
       "      <td>172.27.70.110:45432.0</td>\n",
       "      <td>192.168.1.184:443.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>0.532008</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>-1.533133</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.006729</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>133243</th>\n",
       "      <td>172.16.116.223:60210.0</td>\n",
       "      <td>192.168.1.195:17076.0</td>\n",
       "      <td>-0.141989</td>\n",
       "      <td>-0.326613</td>\n",
       "      <td>-0.086422</td>\n",
       "      <td>-0.026786</td>\n",
       "      <td>-0.022974</td>\n",
       "      <td>1.205621</td>\n",
       "      <td>-0.007051</td>\n",
       "      <td>-0.017000</td>\n",
       "      <td>...</td>\n",
       "      <td>0.032353</td>\n",
       "      <td>0.032008</td>\n",
       "      <td>0.030573</td>\n",
       "      <td>0.031656</td>\n",
       "      <td>-0.002745</td>\n",
       "      <td>-0.00124</td>\n",
       "      <td>0.025943</td>\n",
       "      <td>-0.008069</td>\n",
       "      <td>-0.014919</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>681516 rows × 33 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                         src_ip                 dst_ip     proto   service  \\\n",
       "1410016   172.27.214.71:31971.0    192.168.1.46:4372.0 -0.141989 -0.326613   \n",
       "200517   172.26.161.210:42846.0    192.168.1.184:443.0 -0.141989 -0.326613   \n",
       "1428994  172.16.225.203:62698.0  192.168.1.169:16353.0 -0.141989 -0.326613   \n",
       "1078536   172.19.241.97:49470.0    192.168.1.184:443.0 -0.141989 -0.326613   \n",
       "256376     172.20.96.45:44682.0     192.168.1.190:80.0 -0.141989  2.202699   \n",
       "...                         ...                    ...       ...       ...   \n",
       "507930     172.26.220.2:60854.0     192.168.1.190:80.0 -0.141989  2.202699   \n",
       "1739336      172.17.44.1:4635.0   192.168.1.152:4635.0 -0.141989 -0.326613   \n",
       "347110    172.28.144.97:60159.0  192.168.1.190:12201.0 -0.141989 -0.326613   \n",
       "6363      172.27.70.110:45432.0    192.168.1.184:443.0 -0.141989 -0.326613   \n",
       "133243   172.16.116.223:60210.0  192.168.1.195:17076.0 -0.141989 -0.326613   \n",
       "\n",
       "         duration  src_bytes  dst_bytes  conn_state  missed_bytes  src_pkts  \\\n",
       "1410016 -0.086422  -0.026786  -0.022974    1.205621     -0.007051 -0.017000   \n",
       "200517   0.525077  -0.026786  -0.022974   -1.533133     -0.007051 -0.006729   \n",
       "1428994 -0.086422  -0.026786  -0.022974   -0.412740     -0.007051 -0.017000   \n",
       "1078536  0.523792  -0.026786  -0.022974   -1.533133     -0.007051 -0.006729   \n",
       "256376  -0.085307  -0.026779  -0.022920    0.500845     -0.007051  0.003542   \n",
       "...           ...        ...        ...         ...           ...       ...   \n",
       "507930  -0.081312  -0.026778  -0.022920   -1.518812     -0.007007 -0.006729   \n",
       "1739336 -0.086420  -0.026786  -0.022974   -0.412740     -0.007051 -0.017000   \n",
       "347110  -0.086420  -0.026786  -0.022974   -0.412740     -0.007051 -0.017000   \n",
       "6363     0.532008  -0.026786  -0.022974   -1.533133     -0.007051 -0.006729   \n",
       "133243  -0.086422  -0.026786  -0.022974    1.205621     -0.007051 -0.017000   \n",
       "\n",
       "         ...  ssl_established  http_trans_depth  http_method  http_version  \\\n",
       "1410016  ...         0.032353          0.032008     0.030573      0.031656   \n",
       "200517   ...         0.032353          0.032008     0.030573      0.031656   \n",
       "1428994  ...         0.032353          0.032008     0.030573      0.031656   \n",
       "1078536  ...         0.032353          0.032008     0.030573      0.031656   \n",
       "256376   ...         0.032353          0.032008     0.030573      0.031656   \n",
       "...      ...              ...               ...          ...           ...   \n",
       "507930   ...         0.032353          0.032008     0.030573      0.031656   \n",
       "1739336  ...         0.032353          0.032008     0.030573      0.031656   \n",
       "347110   ...         0.032353          0.032008     0.030573      0.031656   \n",
       "6363     ...         0.032353          0.032008     0.030573      0.031656   \n",
       "133243   ...         0.032353          0.032008     0.030573      0.031656   \n",
       "\n",
       "         http_request_body_len  http_response_body_len  http_status_code  \\\n",
       "1410016              -0.002745                -0.00124          0.025943   \n",
       "200517               -0.002745                -0.00124          0.025943   \n",
       "1428994              -0.002745                -0.00124          0.025943   \n",
       "1078536              -0.002745                -0.00124          0.025943   \n",
       "256376               -0.002745                -0.00124          0.025943   \n",
       "...                        ...                     ...               ...   \n",
       "507930               -0.002745                -0.00124          0.025943   \n",
       "1739336              -0.002745                -0.00124          0.025943   \n",
       "347110               -0.002745                -0.00124          0.025943   \n",
       "6363                 -0.002745                -0.00124          0.025943   \n",
       "133243               -0.002745                -0.00124          0.025943   \n",
       "\n",
       "         http_orig_mime_types  http_resp_mime_types  label  \n",
       "1410016             -0.008069             -0.014919      8  \n",
       "200517              -0.008069             -0.014919      1  \n",
       "1428994             -0.008069             -0.014919      8  \n",
       "1078536             -0.008069             -0.014919      1  \n",
       "256376              -0.008069             -0.014919      3  \n",
       "...                       ...                   ...    ...  \n",
       "507930              -0.008069             -0.014919      3  \n",
       "1739336             -0.008069             -0.014919      2  \n",
       "347110              -0.008069             -0.014919      8  \n",
       "6363                -0.008069             -0.014919      1  \n",
       "133243              -0.008069             -0.014919      8  \n",
       "\n",
       "[681516 rows x 33 columns]"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_test['h'] = X_test[ cols_to_norm ].values.tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [],
   "source": [
    "G_test = nx.from_pandas_edgelist(X_test, \"src_ip\", \"dst_ip\", ['h','label'],create_using=nx.MultiGraph())\n",
    "G_test = G_test.to_directed()\n",
    "G_test = from_networkx(G_test,edge_attrs=['h','label'] )\n",
    "actual = G_test.edata.pop('label')\n",
    "G_test.ndata['feature'] = th.ones(G_test.num_nodes(),G.ndata['h'].shape[2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [],
   "source": [
    "G_test.ndata['feature'] = th.reshape(G_test.ndata['feature'], (G_test.ndata['feature'].shape[0], 1, G_test.ndata['feature'].shape[1]))\n",
    "G_test.edata['h'] = th.reshape(G_test.edata['h'], (G_test.edata['h'].shape[0], 1, G_test.edata['h'].shape[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [],
   "source": [
    "G_test = G_test.to('cuda:0')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [],
   "source": [
    "import timeit\n",
    "start_time = timeit.default_timer()\n",
    "node_features_test = G_test.ndata['feature']\n",
    "edge_features_test = G_test.edata['h']\n",
    "test_pred = model(G_test, node_features_test, edge_features_test).cuda()\n",
    "elapsed = timeit.default_timer() - start_time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.09727129400016565 seconds\n"
     ]
    }
   ],
   "source": [
    "print(str(elapsed) + ' seconds')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_pred = test_pred.argmax(1)\n",
    "test_pred = th.Tensor.cpu(test_pred).detach().numpy()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [],
   "source": [
    "actual = le.inverse_transform(actual)\n",
    "test_pred = le.inverse_transform(test_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import plot_confusion_matrix\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "\n",
    "def plot_confusion_matrix(cm,\n",
    "                          target_names,\n",
    "                          title='Confusion matrix',\n",
    "                          cmap=None,\n",
    "                          normalize=True):\n",
    "    \n",
    "    import matplotlib.pyplot as plt\n",
    "    import numpy as np\n",
    "    import itertools\n",
    "\n",
    "    accuracy = np.trace(cm) / float(np.sum(cm))\n",
    "    misclass = 1 - accuracy\n",
    "\n",
    "    if cmap is None:\n",
    "        cmap = plt.get_cmap('Blues')\n",
    "\n",
    "    plt.figure(figsize=(12, 12))\n",
    "    plt.imshow(cm, interpolation='nearest', cmap=cmap)\n",
    "    plt.title(title)\n",
    "    plt.colorbar()\n",
    "\n",
    "    if target_names is not None:\n",
    "        tick_marks = np.arange(len(target_names))\n",
    "        plt.xticks(tick_marks, target_names, rotation=45)\n",
    "        plt.yticks(tick_marks, target_names)\n",
    "\n",
    "    if normalize:\n",
    "        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n",
    "\n",
    "\n",
    "    thresh = cm.max() / 1.5 if normalize else cm.max() / 2\n",
    "    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n",
    "        if normalize:\n",
    "            plt.text(j, i, \"{:0.4f}\".format(cm[i, j]),\n",
    "                     horizontalalignment=\"center\",\n",
    "                     color=\"white\" if cm[i, j] > thresh else \"black\")\n",
    "        else:\n",
    "            plt.text(j, i, \"{:,}\".format(cm[i, j]),\n",
    "                     horizontalalignment=\"center\",\n",
    "                     color=\"white\" if cm[i, j] > thresh else \"black\")\n",
    "\n",
    "\n",
    "    plt.tight_layout()\n",
    "    plt.ylabel('True label')\n",
    "    plt.xlabel('Predicted label\\naccuracy={:0.4f}; misclass={:0.4f}'.format(accuracy, misclass))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0kAAANYCAYAAAAR86Z+AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAADuNklEQVR4nOzdd3xT1f/H8denlCkge4NsCgVaKFtQQKagDJEhIDLEvfdWFFHcyFD8qgz5iYrIEhFkg+wpewhKAdkbBVrO74+EmkILCG2Stu/n45FHk3PPvfmc3JubfnLOPTHnHCIiIiIiIuIREugAREREREREgomSJBERERERER9KkkRERERERHwoSRIREREREfGhJElERERERMRHaKADEBERERGRxKXLfp1zMX8HOoyLcn/v+9k51yzQcSQVJUkiIiIiIkHMxfxNxnLtAx3GRf2zclCeQMeQlDTcTkRERERExIeSJBERERERER8abiciIiIiEtQMTH0b/qRXW0RERERExIeSJBERERERER8abiciIiIiEswMMAt0FGmKepJERERERER8KEkSERERERHxoSRJRERERETEh65JEhEREREJdpoC3K/0aouIiIiIiPhQkiQiIiIiIuJDw+1ERERERIKdpgD3K/UkiYiIiIiI+FCSJCIiIiIi4kNJkoiIiIhIUDPP7HbBfLtUC8wymdliM1tlZmvN7DVv+TAz22ZmK723SG+5mdkAM9tiZqvNrKrPtrqZ2WbvrZtPeZSZ/eZdZ4CZZ4yimeUys2ne+tPMLOel4lWSJCIiIiIiye0U0NA5FwFEAs3MrJZ32VPOuUjvbaW3rDlQxnvrDQwBT8IDvALUBGoAr/gkPUOAu33Wa+YtfxaY7pwrA0z3Pr4oJUkiIiIiIpKsnMdx78P03pu7yCqtgBHe9RYCOcysINAUmOacO+icOwRMw5NwFQSyO+cWOuccMAJo7bOt4d77w33KE6UkSURERERErlYeM1vqc+t9fgUzS2dmK4G9eBKdRd5Ffb1D6j4ws4zessLADp/Vo71lFyuPTqAcIL9zbrf3/l9A/ks1RlOAi4iIiIgEu+CfAny/c67axSo452KBSDPLAfxgZhWB5/AkLhmAocAzQJ/kCtI558zsYj1YgHqSRERERETEj5xzh4GZQDPn3G7vkLpTwJd4rjMC2AkU9VmtiLfsYuVFEigH2OMdjof3795LxagkSUREREREkpWZ5fX2IGFmmYHGwAaf5MXwXCu0xrvKBOBO7yx3tYAj3iFzPwNNzCynd8KGJsDP3mVHzayWd1t3AuN9tnVuFrxuPuWJ0nA7EREREZFgZlzWNNtBriAw3MzS4emo+dY5N8nMZphZXjytXAnc660/GbgZ2AKcBLoDOOcOmtnrwBJvvT7OuYPe+/cDw4DMwE/eG8BbwLdm1hP4A2h/qWDNM/mDiIiIiIgEo5CsBVzGit0uXTGA/lnUf9mlrklKSVJ8SioiIiIiIpKUNNxORERERCSoWUqY3S5VUU+SiIiIiIiIDyVJIiIiIiIiPjTcTkREREQk2KX82e1SFL3aIiIiIiIiPpQkiYiIiIiI+FCSJCIiIiIi4kPXJImIiIiIBDtNAe5X6kkSERERERHxoSRJRERERETEh4bbiYiIiIgENdMU4H6mV1tERERERMSHkiQREREREREfGm4nIiIiIhLMDM1u52fqSRIREREREfGhJElERERERMSHhtuJiIiIiAQ7zW7nV3q1RUREREREfChJEhERERER8aEkSURERERExIeuSRIRERERCWqma5L8TK+2iIiIiIiIDyVJIiIiIiIiPjTcTkREREQk2IVYoCNIU9STJCIiIiIi4kNJkoiIiIiIiA8NtxMRERERCWaGZrfzM73aIiIiIiIiPpQkiYiIiIiI+NBwOxERERGRYGea3c6f1JMkIiIiIiLiQ0mSiIiIiIiIDyVJIiIiIiIiPnRNkoiIiIhIUDNNAe5nerVFRERERER8KEkSERERERHxoeF2IiIiIiLBTlOA+5V6kkRERERERHwoSRIREREREfGh4XYiIiIiIsFOs9v5lV5tERERERERH0qSREREREREfChJEhERERER8aFrkkREREREgpmZpgD3M/UkiYiIiIiI+FCSJCIiIiIi4kPD7UREREREgp2mAPcrvdoiIiIiIiI+lCSJiIiIiIj40HA7EREREZFgp9nt/Eo9SSIiIiIiIj6UJImIiIiIiPjQcDsRERERkaBmmt3Oz/Rqi4iIiIiI+FCSJCIiIiIi4kNJkoiIiIiIiA9dkyQiIiIiEuw0BbhfqSdJRERERETEh5IkERERERERHxpuJyIiIiISzAxNAe5nerVFRERERER8KEkSERERERHxoeF2IiIiIiJBzTTczs/0aouIiIiIiPhQkiQiIiIiIuJDw+1ERERERIKdfkzWr9STJCIiIiIi4kNJkohIKmJmmc1sopkdMbPvrmI7nc1salLGFghm9pOZdQt0HCIikrIoSRIRCQAzu8PMlprZcTPb7f1nvm4SbLodkB/I7Zy7/Uo34pwb5ZxrkgTxxGNm9c3MmdkP55VHeMtnXeZ2XjWzry5VzznX3Dk3/ArDFRGRNErXJImI+JmZPQ48C9wL/AycBpoBrYB5V7n564BNzrmYq9xOctoH1Daz3M65A96ybsCmpHoCMzPAnHNnk2qbIiIBpSnA/UqvtoiIH5nZtUAf4AHn3Fjn3Ann3Bnn3ETn3FPeOhnN7EMz2+W9fWhmGb3L6ptZtJk9YWZ7vb1Q3b3LXgNeBjp4e6h6nt/jYmbFvT02od7Hd5nZ72Z2zMy2mVlnn/J5PuvVMbMl3mF8S8ysjs+yWWb2upnN925nqpnlucjLcBoYB3T0rp8O6ACMOu+1+sjMdpjZUTNbZmb1vOXNgOd92rnKJ46+ZjYfOAmU9Jb18i4fYmbf+2z/bTOb7k2oRERE4ihJEhHxr9pAJuCHi9R5AagFRAIRQA3gRZ/lBYBrgcJAT2CQmeV0zr0CvAl845zL6pz7/GKBmNk1wACguXMuG1AHWJlAvVzAj966uYH3gR/NLLdPtTuA7kA+IAPw5MWeGxgB3Om93xRYA+w6r84SPK9BLuD/gO/MLJNzbsp57YzwWacr0BvIBvxx3vaeACp5E8B6eF67bs45d4lYRUQkjVGSJCLiX7mB/ZcYDtcZ6OOc2+uc2we8huef/3POeJefcc5NBo4D5a4wnrNARTPL7Jzb7Zxbm0CdFsBm59xI51yMc+5rYANwi0+dL51zm5xzfwPf4kluEuWc+xXIZWbl8CRLIxKo85Vz7oD3Od8DMnLpdg5zzq31rnPmvO2dxPM6vg98BTzknIu+xPZERIKDWXDfUhklSSIi/nUAyHNuuFsiChG/F+QPb1ncNs5Lsk4CWf9rIM65E3iGud0L7DazH80s7DLiORdTYZ/Hf11BPCOBB4EGJNCzZmZPmtl67xC/w3h6zy42jA9gx8UWOucWAb8DhieZExERuYCSJBER/1oAnAJaX6TOLjwTMJxTjAuHol2uE0AWn8cFfBc65352zjUGCuLpHfrsMuI5F9POK4zpnJHA/cBkby9PHO9wuKeB9kBO51wO4Aie5AYgsSFyFx06Z2YP4OmR2uXdvoiIyAWUJImI+JFz7gieyRUGmVlrM8tiZunNrLmZ9fdW+xp40czyeidAeBnP8LArsRK4wcyKeSeNeO7cAjPLb2atvNcmncIzbC+h2eAmA2W905aHmlkHoAIw6QpjAsA5tw24Ec81WOfLBsTgmQkv1MxeBrL7LN8DFDe7/OmezKws8AbQBc+wu6fNLPLKohcR8SMzz+x2wXxLZVJfi0REgpz3+prH8UzGsA/PELEH8cz4Bp5/5JcCq4HfgOXesit5rmnAN95tLSN+YhPijWMXcBBPwnJfAts4ALTEM/HBATw9MC2dc/uvJKbztj3POZdQL9nPwBQ804L/AfxD/KF0534o94CZLb/U83iHN34FvO2cW+Wc24xnhryR52YOFBEROcc0qY+IiIiISPAKyVncZaz/4qUrBtA/4+5e5pyrFug4kop+TFZEREREJNilwhnkgpmG24mIiIiIiPhQkiQiIiIiIuJDSZKIiIiIiIgPXZPkJ3ny5HHFrise6DD8Lq2Ono05mzYnRAkNSat7XEREUrrly5ftd87lDXQciTFdk+RXSpL8pNh1xZm/cEmgw/C7tPqGPnzidKBDCIgc12QIdAgiIiJXJHN6+yPQMUjw0HA7ERERERERH+pJEhEREREJYkbaHZ0TKOpJEhERERER8aEkSURERERExIeG24mIiIiIBDMj7U4ZHCDqSRIREREREfGhJElERERERMSHkiQREREREREfuiZJRERERCSomaYA9zP1JImIiIiIiPhQkiQiIiIiIuJDw+1ERERERIKchtv5l3qSREREREREfChJEhERERER8aHhdiIiIiIiQU7D7fxLPUkiIiIiIiI+lCSJiIiIiIj40HA7EREREZEgp+F2/qWeJBERERERER9KkkRERERERHwoSRIREREREfGha5JERERERIKZeW/iN+pJSmHuubsH1xXOT7XISgkuHzliGMUK5aNmtSrUrFaFL7/4X7zlR48epXSJojz2yINxZadPn+aB+3pTuUI5IiuWZ9zY75O1Dclt6s9TqBxejvCw0rzT/61Ah/Of7IzewW0tm3BDzQhurBXJZ0M+BmDN6lW0aFSPRnWr07R+bVYsW3LBuqdPn+bR+++mQZ2q3HR9NX6dOxuA48eO0ahu9bhbhZKFeOnZJwDY8ecf3H5r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ktKHT6c0aa0n6b8YDTxlZivMrFSggxEREREREf9IMz1JzrntQEWfx3clsmyYt2w+8acAr+9TfxYwy+dxfUREREREJFVIM0mSiIiIiEhKpcF2/qXhdiIiIiIiIj6UJImIiIiIiPjQcDsRERERkSBmBiGa3c6vEk2SzOxjINFfmnXOPZwsEYmIiIiIiATQxXqSlvotChERERERkSCRaJLknBvu+9jMsjjnTiZ/SCIiIiIi4kuj7fzrkhM3mFltM1sHbPA+jjCzwckemYiIiIiISABczux2HwJNgQMAzrlVwA3JGJOIiIiIiEjAXNYU4M65HecVxSZDLCIiIiIiIgF3OVOA7zCzOoAzs/TAI8D65A1LRERERETOMV2U5FeX05N0L/AAUBjYBUR6H4uIiIiIiKQ6l+xJcs7tBzr7IRYREREREZGAu5zZ7Uqa2UQz22dme81svJmV9EdwIiIiIiLimQI8mG+pzeUMt/s/4FugIFAI+A74OjmDEhERERERCZTLSZKyOOdGOudivLevgEzJHZiIiIiIiEggJHpNkpnl8t79ycyeBUYDDugATPZDbCIiIiIiaZ5hhKTGMW1B7GITNyzDkxSd2yP3+CxzwHPJFZSIiIiIiEigJJokOedK+DMQERERERGRYHA5PyaLmVUEKuBzLZJzbkRyBSUiIiIiIhIol0ySzOwVoD6eJGky0ByYByhJEhERERFJbql0mu1gdjmz27UDbgL+cs51ByKAa5M1KhERERERkQC5nCTpb+fcWSDGzLIDe4GiyRuWiIiIiIhIYFzONUlLzSwH8BmeGe+OAwuSMygREREREfmXabydX10ySXLO3e+9+4mZTQGyO+dWJ29YIiIiIiIigXGxH5OterFlzrnlyROSiIgEuz1H/gl0CAGR/9pMl66UCp096wIdQkCEhOibe5G06mI9Se9dZJkDGiZxLCIiIiIikoDLmUhAks7Ffky2gT8DERERERERCQZKSkVERERERHxczux2IiIiIiISIIZmt/M39SSJiIiIiIj4uGSSZB5dzOxl7+NiZlYj+UMTERERERHxv8vpSRoM1AY6eR8fAwYlW0QiIiIiIiIBdDnXJNV0zlU1sxUAzrlDZpYhmeMSEREREREv/WyXf11OT9IZM0uH57eRMLO8wNlkjUpERERERCRALidJGgD8AOQzs77APODNZI1KREREREQkQC453M45N8rMlgE34ZmBsLVzbn2yRyYiIiIiIoCG2/nbJZMkMysGnAQm+pY55/5MzsBEREREREQC4XImbvgRz/VIBmQCSgAbgfBkjEtERERERCQgLme4XSXfx2ZWFbg/2SISEREREZE4ZmCm8Xb+dDkTN8TjnFsO1EyGWERERERERALucq5JetznYQhQFdiVbBGJiIiIiIgE0OVck5TN534MnmuUvk+ecERERERE5Hya3c6/LpokeX9ENptz7kk/xSMiIiIiIhJQiV6TZGahzrlY4Ho/xiMiIiIiIhJQF+tJWozn+qOVZjYB+A44cW6hc25sMscmIiIiIiLid5dzTVIm4ADQkH9/L8kBSpJERERERPxAM4D718WSpHzeme3W8G9ydI5L1qhEREREREQC5GJJUjogK/GTo3OUJImIiIiISKp0sR+T3e2c6+Ocey2BWx+/RShXJTY2llrVqtC2VctAh5LkDh8+TKcO7YioGEZkpfIsXLCA5555ioiKYVSvUpn27dpw+PBhAA4cOEDTRg3IkyMrjz78YGADT2KJ7ePHH32YPDmyBiiq5LNp40ZqRkXG3fLlys7HH33IG31epeR1hePKp/w0OdChXrXE2vr9mO+oGhFOlgwhLFu6NK5+SjrOY2NjublBLXp0agvA8P8N4cbq4RTPk5mDB/YnuM64776mef2acbcSebOw9rdV8er06tyOJnWj4pUN+2wwDWtF0Pj6qvR79fnkaVASuKdXD4oVykdUZMW4stdeeYnqVSpTMyqSls2bsGtX/J8pXLpkCVkzhTL2+zH+DveKRO/YQfMmDYmKCKdaZEUGffzRBXX+/OMPbm7aiBpRETRr3ICd0dFxy158/hmqValEtSqVGPPdN3HlvXt1p0LZktSqXoVa1auwatVKfzTnsiW0b32dOnWKLnd0IDysNPXq1OSP7duBxN/TJ0+epM2tLYioGEbViHBefP5ZfzQjSf3zzz/UrV2DGlUjqBoRzuuvvQLA9m3bqFenJuFhpelyRwdOnz4d4EiDgwEhZkF9S20uliSlvtamQQMHfES58uUDHUayePKxR2jSpBmr1mxg8bJVhJUvz02NGrNs5RqWrFhNmTJleeftfgBkypSJl199nX5vvxvgqJNeQvt42dKlHD50KEARJa+y5cqxaNlKFi1bya+Ll5ElSxZubd0GgIceeSxu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",
      "text/plain": [
       "<Figure size 864x864 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.metrics import confusion_matrix\n",
    "\n",
    "plot_confusion_matrix(cm = confusion_matrix(actual, test_pred), \n",
    "                      normalize    = False,\n",
    "                      target_names = np.unique(actual),\n",
    "                      title        = \"Confusion Matrix\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "    backdoor     0.1771    0.0506    0.0787     30536\n",
      "        ddos     0.9956    0.9694    0.9823    369624\n",
      "         dos     0.5892    0.9608    0.7304    202244\n",
      "   injection     0.7749    0.8894    0.8282     27238\n",
      "        mitm     0.0973    0.8743    0.1752       692\n",
      "      normal     0.9394    0.8812    0.9094     47372\n",
      "    password     0.9324    0.8915    0.9115     81554\n",
      "  ransomware     0.9003    0.9855    0.9410     48066\n",
      "    scanning     0.9795    0.7584    0.8549    428996\n",
      "         xss     0.9732    0.9208    0.9463    126710\n",
      "\n",
      "    accuracy                         0.8678   1363032\n",
      "   macro avg     0.7359    0.8182    0.7358   1363032\n",
      "weighted avg     0.8959    0.8678    0.8695   1363032\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import classification_report\n",
    "print(classification_report(actual, test_pred, digits=4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [],
   "source": [
    "#th.save(model.state_dict(), 'model.pt')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "    backdoor       0.18      0.05      0.08     30536\n",
      "        ddos       1.00      0.97      0.98    369624\n",
      "         dos       0.59      0.96      0.73    202244\n",
      "   injection       0.77      0.89      0.83     27238\n",
      "        mitm       0.10      0.87      0.18       692\n",
      "      normal       0.94      0.88      0.91     47372\n",
      "    password       0.93      0.89      0.91     81554\n",
      "  ransomware       0.90      0.99      0.94     48066\n",
      "    scanning       0.98      0.76      0.85    428996\n",
      "         xss       0.97      0.92      0.95    126710\n",
      "\n",
      "    accuracy                           0.87   1363032\n",
      "   macro avg       0.74      0.82      0.74   1363032\n",
      "weighted avg       0.90      0.87      0.87   1363032\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import classification_report\n",
    "print(classification_report(actual, test_pred, digits=2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [],
   "source": [
    "report = classification_report(actual, test_pred, digits=4, output_dict=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame(report).transpose()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.to_csv('unsw_ton_iot_agg_report.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>precision</th>\n",
       "      <th>recall</th>\n",
       "      <th>f1-score</th>\n",
       "      <th>support</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>backdoor</th>\n",
       "      <td>0.177070</td>\n",
       "      <td>0.050629</td>\n",
       "      <td>0.078743</td>\n",
       "      <td>3.053600e+04</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>ddos</th>\n",
       "      <td>0.995610</td>\n",
       "      <td>0.969426</td>\n",
       "      <td>0.982343</td>\n",
       "      <td>3.696240e+05</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>dos</th>\n",
       "      <td>0.589169</td>\n",
       "      <td>0.960825</td>\n",
       "      <td>0.730439</td>\n",
       "      <td>2.022440e+05</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>injection</th>\n",
       "      <td>0.774878</td>\n",
       "      <td>0.889382</td>\n",
       "      <td>0.828191</td>\n",
       "      <td>2.723800e+04</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mitm</th>\n",
       "      <td>0.097329</td>\n",
       "      <td>0.874277</td>\n",
       "      <td>0.175159</td>\n",
       "      <td>6.920000e+02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>normal</th>\n",
       "      <td>0.939421</td>\n",
       "      <td>0.881238</td>\n",
       "      <td>0.909400</td>\n",
       "      <td>4.737200e+04</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>password</th>\n",
       "      <td>0.932418</td>\n",
       "      <td>0.891544</td>\n",
       "      <td>0.911523</td>\n",
       "      <td>8.155400e+04</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>ransomware</th>\n",
       "      <td>0.900264</td>\n",
       "      <td>0.985541</td>\n",
       "      <td>0.940974</td>\n",
       "      <td>4.806600e+04</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>scanning</th>\n",
       "      <td>0.979534</td>\n",
       "      <td>0.758434</td>\n",
       "      <td>0.854920</td>\n",
       "      <td>4.289960e+05</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>xss</th>\n",
       "      <td>0.973161</td>\n",
       "      <td>0.920843</td>\n",
       "      <td>0.946279</td>\n",
       "      <td>1.267100e+05</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>accuracy</th>\n",
       "      <td>0.867838</td>\n",
       "      <td>0.867838</td>\n",
       "      <td>0.867838</td>\n",
       "      <td>8.678380e-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>macro avg</th>\n",
       "      <td>0.735885</td>\n",
       "      <td>0.818214</td>\n",
       "      <td>0.735797</td>\n",
       "      <td>1.363032e+06</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>weighted avg</th>\n",
       "      <td>0.895856</td>\n",
       "      <td>0.867838</td>\n",
       "      <td>0.869544</td>\n",
       "      <td>1.363032e+06</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              precision    recall  f1-score       support\n",
       "backdoor       0.177070  0.050629  0.078743  3.053600e+04\n",
       "ddos           0.995610  0.969426  0.982343  3.696240e+05\n",
       "dos            0.589169  0.960825  0.730439  2.022440e+05\n",
       "injection      0.774878  0.889382  0.828191  2.723800e+04\n",
       "mitm           0.097329  0.874277  0.175159  6.920000e+02\n",
       "normal         0.939421  0.881238  0.909400  4.737200e+04\n",
       "password       0.932418  0.891544  0.911523  8.155400e+04\n",
       "ransomware     0.900264  0.985541  0.940974  4.806600e+04\n",
       "scanning       0.979534  0.758434  0.854920  4.289960e+05\n",
       "xss            0.973161  0.920843  0.946279  1.267100e+05\n",
       "accuracy       0.867838  0.867838  0.867838  8.678380e-01\n",
       "macro avg      0.735885  0.818214  0.735797  1.363032e+06\n",
       "weighted avg   0.895856  0.867838  0.869544  1.363032e+06"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [],
   "source": [
    "th.save(model.state_dict(), 'unsw_ton_iot_agg_mul.pt')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
